﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Polaris.Common;
using Polaris.Common.RedisHelper;
using Polaris.Domain.Interfaces.Admin;
using Polaris.Domain.Interfaces.WebSite;
using Polaris.Domain.Model.DbEntity;
using Polaris.Domain.Model.DtoWebSite.Article.Response;
using Polaris.Domain.Model.DtoWebSite.Notes.Response;
using Polaris.Domain.Model.Entity.Base;
using Polaris.Domain.Model.Entity.Exception;
using Polaris.Domain.Model.Enum;
using Polaris.Domain.Repository.Interfaces;
using Polaris.EntityFrameworkCore;
using SixLabors.Fonts.Tables.AdvancedTypographic;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace Polaris.Infrastructure.DomainService.WebSite
{
    public class WebArticleService : IWebArticle
    {
        private readonly PolarisDbContext _dbContext;
        private readonly IBaseRepository<Notes> _notes;
        private readonly string _notesName = AppConfig.GetConfigInfo("NotesName");
        private readonly IBaseRepository<Sys_Dictionary_Item> _sys_Dictionary_Item;
        private readonly IBaseRepository<ArticleInfo> _articleInfo;
        private readonly string _notesBaseKey = "notes:web";

        public WebArticleService(PolarisDbContext dbContext, IBaseRepository<Notes> notes, IBaseRepository<Sys_Dictionary_Item> sys_Dictionary_Item, IBaseRepository<ArticleInfo> articleInfo)
        {
            _dbContext = dbContext;
            _notes = notes;
            _sys_Dictionary_Item = sys_Dictionary_Item;
            _articleInfo = articleInfo;
        }

        /// <summary>
        /// 获取文章和闲书集合
        /// </summary>
        /// <param name="pageInfo"></param>
        /// <returns></returns>
        /// <exception cref="CustomException"></exception>
        public async Task<PaginationInfo<ArticleGroupByYearResponse>> GetArticleList(Pagination pageInfo)
        {
            try
            {
                var articleQuery = _dbContext.ArticleInfo
                            .Join(
                                    _dbContext.Sys_Dictionary_Item,
                                    com => com.ArticleType, // 文章类型
                                    item => item.Id,
                                    (com, typeItem) => new
                                    {
                                        articleInfo = com,
                                        typeItem = typeItem.Name // 文章类型
                                    }
                                )
                            .Where(a => !a.articleInfo.IsDelete)
                            .Select(a => new ArticleBase
                            {
                                CreateTime = a.articleInfo.CreateTime,
                                Id = a.articleInfo.Id,
                                IsRedFlag = a.articleInfo.IsRedFlag,
                                TagDescription = a.typeItem,
                                Title = a.articleInfo.Title,
                                Type = (int)ArticleType.Article,
                                Weather = null,
                                Mood = null
                            });
                var noteQuery = _dbContext.Notes
                            .Where(d => !d.IsDelete)
                            .Select(d => new ArticleBase
                            {
                                Id = d.Id,
                                IsRedFlag = d.IsRedFlag,
                                TagDescription = "",
                                Title = d.Title,
                                Type = (int)ArticleType.Notes,
                                CreateTime = d.CreateTime,
                                Mood = d.Mood,
                                Weather = d.Weather
                            });

                var unionQuery = articleQuery.Union(noteQuery);
                // 2. 合并分页查询
                var totalCount = await unionQuery.CountAsync();

                var pagedData = await unionQuery
                    .Union(noteQuery)
                    .OrderByDescending(x => x.CreateTime)
                    .Skip((pageInfo.PageIndex - 1) * pageInfo.PageSize)
                    .Take(pageInfo.PageSize)
                    .ToListAsync();

                // 3. 内存分组处理
                var groupedResult = pagedData
                    .GroupBy(x => x.CreateTime.Year)
                    .Select(g => new ArticleGroupByYearResponse
                    {
                        Year = g.Key.ToString(),
                        ArticleList = g.OrderByDescending(x => x.CreateTime)
                                      .Select(ToArticleListResponse)
                                      .ToList(),
                        Count = g.Count()
                    })
                    .OrderByDescending(g => g.Year)
                    .ToList();

                return new PaginationInfo<ArticleGroupByYearResponse>
                {
                    Result = groupedResult,
                    PageIndex = pageInfo.PageIndex,
                    PageSize = pageInfo.PageSize,
                    TotalNum = totalCount
                };
            }
            catch (Exception ex)
            {
                throw new CustomException(ResultCode.FAIL, ex.Message);
            }
        }

        /// <summary>
        /// 获取最新的闲书
        /// </summary>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<CursorPagedResult<NoteInfoResponse>> GetNewNotes(Guid? id, string fingerprint)
        {
            var notes = new Notes();
            if (id != null)
            {
                notes = await _notes.QueryAll(d => d.Id == id).FirstOrDefaultAsync();
            }
            else
            {
                notes = await _notes.QueryAll(d => d.CreateTime, false).FirstOrDefaultAsync();
            }
            if (notes != null)
            {
                string cacheKey = $"notes:{id}:clients";
                var isLiked = await RedisHelper.SetContainsAsync(cacheKey, fingerprint);
                var previous = await _notes.QueryAll(e => e.CreateTime > notes.CreateTime ||
                                    (e.CreateTime == notes.CreateTime && e.Id != notes.Id))
                        .OrderBy(e => e.CreateTime)
                        .ThenBy(e => e.Id)
                        .Select(e => new
                        {
                            e.Id,
                            e.Title
                        })
                        .FirstOrDefaultAsync();

                var next = await _notes.QueryAll(e => e.CreateTime < notes.CreateTime ||
                                    (e.CreateTime == notes.CreateTime && e.Id != notes.Id))
                        .OrderByDescending(e => e.CreateTime)
                        .ThenByDescending(e => e.Id)
                        .Select(e => new
                        {
                            e.Id,
                            e.Title
                        })
                        .FirstOrDefaultAsync();

                var noteInfo = new NoteInfoResponse()
                {
                    CreateTime = notes.CreateTime.ToString("yyyy年MM月dd日") + " " + notes.CreateTime.ToString("dddd"),
                    Id = notes.Id.ToString(),
                    Browse = notes.Browse,
                    Content = notes.Content,
                    Like = notes.Like,
                    Tags = null,
                    Title = notes.Title,
                    CursorTime = notes.CreateTime,
                    IsComments = notes.IsComments,
                    IsLike = isLiked
                };
                if (notes.NotesUpdateTime.HasValue)
                {
                    noteInfo.LaseUpdateTime = notes.NotesUpdateTime.Value.ToString("yyyy年MM月dd日") + " " + notes.NotesUpdateTime.Value.ToString("dddd");
                }
                var nextTitle = next?.Title;
                if (!string.IsNullOrEmpty(nextTitle))
                {
                    nextTitle = nextTitle.Length > 15 ? (nextTitle.Substring(0, 13) + "...") : nextTitle;
                }
                var previousTitle = previous?.Title;
                if (!string.IsNullOrEmpty(previousTitle))
                {
                    previousTitle = previousTitle.Length > 15 ? (previousTitle.Substring(0, 13) + "...") : previousTitle;
                }
                return new CursorPagedResult<NoteInfoResponse>()
                {
                    Items = noteInfo,
                    NextId = next?.Id.ToString(),
                    NextTitle = nextTitle,
                    PreviousId = previous?.Id.ToString(),
                    PreviousTitle = previousTitle
                };
            }

            return new CursorPagedResult<NoteInfoResponse>();
        }

        /// <summary>
        /// 闲书浏览量
        /// </summary>
        /// <param name="id"></param>
        /// <param name="fingerprint"></param>
        /// <returns></returns>
        public async Task<bool> BrowseNotes(Guid id, string fingerprint)
        {
            try
            {
                var cacheKey = $"notes:{id}:browse";
                //await RedisHelper.KeyDeleteAsync(cacheKey);
                var isBrowse = await RedisHelper.SetContainsAsync(cacheKey, fingerprint);
                if (!isBrowse)
                {
                    var notes = await _notes.QueryAll(d => d.Id == id).FirstAsync();
                    notes.Browse++;
                    _notes.UpdateEntity(notes);
                    await _notes.CommitAsync();
                    await RedisHelper.SetAddAsync(cacheKey, fingerprint, TimeSpan.FromDays(1));
                    return true;
                }
                return false;
            }
            catch (Exception ex)
            {
                throw new CustomException(ex.Message);
            }
        }

        /// <summary>
        /// 闲书浏览量
        /// </summary>
        /// <param name="id"></param>
        /// <param name="fingerprint"></param>
        /// <returns></returns>
        public async Task<bool> BrowseArticle(Guid id, string fingerprint)
        {
            try
            {
                var cacheKey = $"article:{id}:browse";
                await RedisHelper.KeyDeleteAsync(cacheKey);
                var isBrowse = await RedisHelper.SetContainsAsync(cacheKey, fingerprint);
                if (!isBrowse)
                {
                    var article = await _articleInfo.QueryAll(d => d.Id == id).FirstAsync();
                    article.Browse++;
                    _articleInfo.UpdateEntity(article);
                    await _articleInfo.CommitAsync();
                    await RedisHelper.SetAddAsync(cacheKey, fingerprint, TimeSpan.FromDays(1));
                    return true;
                }
                return false;
            }
            catch (Exception ex)
            {
                throw new CustomException(ex.Message);
            }
        }


        /// <summary>
        /// 根据id和类型获取文章或闲书内容
        /// </summary>
        /// <param name="id"></param>
        /// <param name="articleType"></param>
        /// <returns></returns>
        public async Task<ArticleContentResponse> GetArticleContentById(string id, ArticleType articleType)
        {
            var result = new ArticleContentResponse();
            if (articleType == ArticleType.Article)
            {
                Expression<Func<ArticleInfo, bool>> exp = e => e.IsDelete == false;
                exp = exp.And(e => !e.IsDelete && e.Id.ToString() == id);

                var linqStr = _dbContext.ArticleInfo
                     .Where(exp)
                     .Join(
                         _dbContext.ArticleDictionaryRelation,
                         a => a.Id,
                         at => at.ArticleId,
                         (a, at) => new
                         {
                             articleInfo = a,
                             relation = at
                         }
                     )
                     .Join(
                         _dbContext.Sys_Dictionary_Item,
                         com => com.relation.DictionaryId,
                         item => item.Id,
                         (com, item) => new
                         {
                             articleInfo = com.articleInfo,
                             relation = com.relation,
                             tagItem = item
                         }
                     )
                     .Join(
                        _dbContext.ArticleContent,
                        com => com.articleInfo.Id,
                        con => con.ArticleId,
                        (com, con) => new
                        {
                            articleInfo = com.articleInfo,
                            tagItem = com.tagItem,
                            content = con
                        }
                    )
                     .OrderByDescending(d => d.articleInfo.CreateTime)
                     .GroupBy(
                         result => new
                         {
                             result.articleInfo.Id,
                             result.articleInfo.Title,
                             result.articleInfo.CreateTime,
                             result.articleInfo.Browse,
                             result.articleInfo.Enable,
                             result.articleInfo.Like,
                         },
                         (key, g) => new ArticleContentResponse()
                         {
                             Id = key.Id.ToString(),
                             Title = key.Title,
                             Browse = key.Browse,
                             Like = key.Like,
                             LaseUpdateTime = g.First().content.LastUpdateTime.HasValue ? g.First().content.LastUpdateTime.Value.ToString("yyyy年MM月dd日") : null,
                             Tags = g.Select(x => x.tagItem.Name).ToList(), // 获取标签列表
                             Content = g.First().content.Content,
                             CreateTime = key.CreateTime.ToString("yyyy年MM月dd日") + " " + key.CreateTime.ToString("dddd"),
                         }
                );

                result = await linqStr.FirstOrDefaultAsync();
            }
            else if (articleType == ArticleType.Notes)
            {
                result = await _notes.QueryAll(d => d.Id.ToString() == id)
                    .Select(d => new ArticleContentResponse()
                    {
                        Id = d.Id.ToString(),
                        Browse = d.Browse,
                        Content = d.Content,
                        CreateTime = d.CreateTime.ToString("yyyy年MM月dd号") + " " + d.CreateTime.ToString("dddd"),
                        Like = d.Like,
                        Title = d.Title,
                        LaseUpdateTime = null,
                        Mood = d.Mood,
                        MoodIcon = d.MoodIcon,
                        Tags = null,
                        Weather = d.Weather,
                        WeatherIcon = d.WeatherIcon
                    })
                    .FirstOrDefaultAsync();
            }
            return result;
        }

        /// <summary>
        /// 根据id获取文章消息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<ArticleInfoResponse> GetArticleInfoById(string id, string fingerprint)
        {
            try
            {
                //var cacheKey = $"{_notesBaseKey}:id:{id}";
                //var redisData = await RedisHelper.GetHashAsync<ArticleInfoResponse>(cacheKey);
                //if (redisData != null)
                //{
                //    return redisData;
                //}

                //Expression<Func<ArticleInfo, bool>> exp = e => e.IsDelete == false;
                //exp = exp.And(e => !e.IsDelete && e.Id.ToString() == id);

                //var linqStr = _dbContext.ArticleInfo
                //     .Where(exp)
                //     .Join(
                //         _dbContext.ArticleDictionaryRelation,
                //         a => a.Id,
                //         at => at.ArticleId,
                //         (a, at) => new
                //         {
                //             articleInfo = a,
                //             relation = at
                //         }
                //     )
                //     .Join(
                //         _dbContext.Sys_Dictionary_Item,
                //         com => com.relation.DictionaryId,
                //         item => item.Id,
                //         (com, item) => new
                //         {
                //             articleInfo = com.articleInfo,
                //             relation = com.relation,
                //             tagItem = item
                //         }
                //     )
                //     .Join(
                //        _dbContext.ArticleContent,
                //        com => com.articleInfo.Id,
                //        con => con.ArticleId,
                //        (com, con) => new
                //        {
                //            articleInfo = com.articleInfo,
                //            tagItem = com.tagItem,
                //            content = con
                //        }
                //    )
                //     .OrderByDescending(d => d.articleInfo.CreateTime)
                //     .GroupBy(
                //         result => new
                //         {
                //             result.articleInfo.Id,
                //             result.articleInfo.Title,
                //             result.articleInfo.CreateTime,
                //             result.articleInfo.Browse,
                //             result.articleInfo.Enable,
                //             result.articleInfo.Like,
                //         },
                //         (key, g) => new ArticleInfoResponse()
                //         {
                //             Id = key.Id.ToString(),
                //             Title = key.Title,
                //             Browse = key.Browse,
                //             Like = key.Like,
                //             LaseUpdateTime = g.First().content.LastUpdateTime.HasValue ? g.First().content.LastUpdateTime.Value.ToString("yyyy年MM月dd日") : null,
                //             Tags = g.Select(x => x.tagItem.Name).ToList(), // 获取标签列表
                //             Content = g.First().content.Content,
                //             CreateTime = key.CreateTime.ToString("yyyy年MM月dd日") + " " + key.CreateTime.ToString("dddd"),
                //         }
                //);

                //var result = await linqStr.FirstOrDefaultAsync();
                ////await RedisHelper.SetHashAsync(cacheKey, result, TimeSpan.FromMinutes(new Random().Next(-5, 5)));
                //return result;

                string cacheKey = $"article:{id}:clients";
                var isLiked = await RedisHelper.SetContainsAsync(cacheKey, fingerprint);
                // 步骤1：获取所有符合条件的文章（带排序）
                var baseQuery = _dbContext.ArticleInfo
                    .Where(e => !e.IsDelete)
                    .Join(_dbContext.ArticleDictionaryRelation,
                        a => a.Id,
                        at => at.ArticleId,
                        (a, at) => new { a, at })
                    .Join(_dbContext.Sys_Dictionary_Item,
                        com => com.at.DictionaryId,
                        item => item.Id,
                        (com, item) => new { com.a, item })
                    .Join(_dbContext.ArticleContent,
                        com => com.a.Id,
                        con => con.ArticleId,
                        (com, con) => new { com.a, com.item, con })
                    .OrderByDescending(d => d.a.CreateTime);

                var a = baseQuery.ToList();
                // 步骤2：获取完整排序列表（用于定位相邻文章）
                var fullList = await baseQuery
                    .Select(x => new ArticleBrief
                    {
                        Id = x.a.Id.ToString(),
                        Title = x.a.Title,
                        IsCurrent = x.a.Id.ToString() == id,
                        CreateTime = x.a.CreateTime
                    })
                    .GroupBy(x => x.Id)
                    .Select(x => x.First())
                    .ToListAsync();
                fullList = fullList.OrderByDescending(x => x.CreateTime).ToList();

                // 步骤3：获取当前文章详细信息
                var result = await baseQuery
                    .Where(d => d.a.Id == Guid.Parse(id))
                    .GroupBy(x => new
                    {
                        x.a.Id,
                        x.a.Title,
                        x.a.CreateTime,
                        x.a.Browse,
                        x.a.Enable,
                        x.a.Like,
                        x.a.IsComments
                    })
                    .Select(g => new ArticleInfoResponse
                    {
                        Id = g.Key.Id.ToString(),
                        Title = g.Key.Title,
                        Browse = g.Key.Browse,
                        Like = g.Key.Like,
                        LaseUpdateTime = g.First().con.LastUpdateTime.HasValue
                            ? g.First().con.LastUpdateTime.Value.ToString("yyyy年MM月dd日")
                            : null,
                        Tags = g.Select(x => x.item.Name).ToList(),
                        Content = g.First().con.Content,
                        CreateTime = g.Key.CreateTime.ToString("yyyy年MM月dd日 dddd"),
                        IsComments = g.Key.IsComments,
                        IsLike = isLiked,
                        AdjacentArticles = new List<ArticleBrief>() // 暂留空位
                    })
                    .FirstOrDefaultAsync();

                // 步骤4：计算相邻文章
                if (result != null && fullList.Any())
                {
                    int currentIndex = fullList.FindIndex(x => x.Id == id) + 1;
                    if (currentIndex >= 0)
                    {
                        int start = Math.Max(0, currentIndex - 3);
                        int takeCount = 5;//Math.Min(5, fullList.Count - start);
                        if (fullList.Count <= 5)
                        {
                            start = 0;
                        }
                        else
                        {
                            if (currentIndex == fullList.Count)
                            {
                                start = fullList.Count - 5;
                            }
                            else if (currentIndex + 2 > fullList.Count)
                            {
                                start -= currentIndex + 2 - fullList.Count;
                            }
                        }

                        result.AdjacentArticles = fullList
                            .Skip(start)
                            .Take(takeCount)
                            .Select(x => new ArticleBrief
                            {
                                Title = x.Title,
                                Id = x.Id,
                                IsCurrent = x.IsCurrent
                            })
                            .ToList();
                    }
                }

                return result;
            }
            catch (Exception ex)
            {
                throw new CustomException(ResultCode.FAIL, ex.Message);
            }
        }

        /// <summary>
        /// 获取推荐文章
        /// </summary>
        /// <param name="type">notes/articles</param>
        /// <returns></returns>
        public async Task<List<RecommendArticleInfoResponse>> GetRecommendArticle(string type)
        {
            var result = new List<RecommendArticleInfoResponse>();
            if (type == "notes")
            {
                result = await _notes.QueryAll(d => !d.IsDelete && d.Enable)
                    .OrderByDescending(d => d.CreateTime)
                    .Skip(0).Take(5)
                    .Select(d => new RecommendArticleInfoResponse()
                    {
                        Id = d.Id.ToString(),
                        CreateTime = d.CreateTime.ToString("dd/MM"),
                        Title = d.Title.Length > 15 ? d.Title.Substring(0, 15) + "..." : d.Title,
                        IsRedFlag = d.IsRedFlag,
                        Type = ArticleType.Notes,
                        TagDescription = $"{(d.Mood != null ? "心情：" + d.Mood + "/" : "")} {(d.Weather != null ? "天气：" + d.Weather + "/" : "")} {_notesName}"
                    })
                    .ToListAsync();
                return result;
            }
            else if (type == "articles")
            {
                Expression<Func<ArticleInfo, bool>> exp = e => e.IsDelete == false;
                exp = exp.And(e => e.Enable);

                var linqStr = _dbContext.ArticleInfo
                     .Where(exp)
                     //.Skip(0).Take(4)
                     .Join(
                         _dbContext.ArticleDictionaryRelation,
                         a => a.Id,
                         at => at.ArticleId,
                         (a, at) => new
                         {
                             articleInfo = a,
                             tag = at.DictionaryId
                         }
                     )
                     .Join(
                        _dbContext.Sys_Dictionary_Item,
                        a => a.tag,
                        tag => tag.Id,
                        (a, tag) => new
                        {
                            articleInfo = a.articleInfo,
                            tag = tag.Name,
                        }
                    )
                     .Join(
                         _dbContext.Sys_Dictionary_Item,
                        a => a.articleInfo.ArticleType,
                        type => type.Id,
                        (a, type) => new
                        {
                            articleInfo = a.articleInfo,
                            tag = a.tag,
                            type = type.Name
                        }
                    )
                     //.OrderByDescending(d => d.articleInfo.IsTop)
                     //.ThenByDescending(d => d.articleInfo.CreateTime)
                     .GroupBy(
                         result => new
                         {
                             result.articleInfo.Id,
                             result.articleInfo.Title,
                             result.articleInfo.CreateTime,
                             result.articleInfo.IsTop,
                             result.articleInfo.Browse,
                             result.articleInfo.Like
                         },
                         (key, g) => new
                         {
                             Id = key.Id.ToString(),
                             Title = key.Title,
                             TypeName = g.FirstOrDefault().type,
                             Tags = g.Select(d => d.tag).ToList(),
                             CreateTime = key.CreateTime,
                             IsTop = key.IsTop,
                             Like = key.Like,
                             Browse = key.Browse
                         })
                     .OrderByDescending(d => d.IsTop)
                     .ThenByDescending(d => d.CreateTime)
                     .Skip(0).Take(4);

                result = await linqStr.Select(d => new RecommendArticleInfoResponse()
                {
                    Browse = d.Browse,
                    CreateTime = d.CreateTime.ToString("yyyy年MM月dd日") + " " + d.CreateTime.ToString("dddd"),
                    Id = d.Id,
                    IsTop = d.IsTop,
                    Like = d.Like,
                    Tags = d.Tags,
                    Title = d.Title,
                    TypeName = d.TypeName,
                    Type = ArticleType.Article
                }).ToListAsync();
            }
            return result;
        }

        /// <summary>
        /// 根据类型获取文章列表
        /// </summary>
        /// <param name="pageInfo"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public async Task<PaginationInfo<ArticleGroupByYearResponse>> GetArticleListByType(Pagination pageInfo, ArticleType type)
        {
            var result = new PaginationInfo<ArticleGroupByYearResponse>
            {
                Result = new List<ArticleGroupByYearResponse>(),
                PageIndex = pageInfo.PageIndex,
                PageSize = pageInfo.PageSize,
                TotalNum = 0
            };
            switch (type)
            {
                case ArticleType.Article:
                    var articleCount = await _dbContext.ArticleInfo
                                .Join(
                                    _dbContext.Sys_Dictionary_Item,
                                    com => com.ArticleType,
                                    item => item.Id,
                                    (com, typeItem) => new { com, typeItem }
                                )
                                .Where(a => !a.com.IsDelete)
                                .CountAsync();
                    var articleQuery = _dbContext.ArticleInfo
                            .Join(
                                    _dbContext.Sys_Dictionary_Item,
                                    com => com.ArticleType, // 文章类型
                                    item => item.Id,
                                    (com, typeItem) => new
                                    {
                                        articleInfo = com,
                                        typeItem = typeItem.Name // 文章类型
                                    }
                                )
                            .Where(a => !a.articleInfo.IsDelete)
                            .OrderByDescending(a => a.articleInfo.CreateTime)
                            .Skip((pageInfo.PageIndex - 1) * pageInfo.PageSize).Take(pageInfo.PageSize)
                            .Select(a => new ArticleBase
                            {
                                CreateTime = a.articleInfo.CreateTime,
                                Id = a.articleInfo.Id,
                                IsRedFlag = a.articleInfo.IsRedFlag,
                                TagDescription = a.typeItem,
                                Title = a.articleInfo.Title,
                                Type = (int)ArticleType.Article,
                                Weather = null,
                                Mood = null
                            });
                    var pageData = await articleQuery.ToListAsync();
                    result.Result = pageData
                         .GroupBy(x => x.CreateTime.Year)
                         .Select(g => new ArticleGroupByYearResponse
                         {
                             Year = g.Key.ToString(),
                             ArticleList = g.OrderByDescending(x => x.CreateTime)
                                      .Select(ToArticleListResponse)
                                      .ToList(),
                             Count = g.Count()
                         })
                        .OrderByDescending(g => g.Year)
                        .ToList();
                    result.TotalNum = articleCount;
                    break;

                case ArticleType.Notes:
                    var noteCount = await _dbContext.Notes
                           .Where(d => !d.IsDelete)
                           .CountAsync();
                    var noteQuery = _dbContext.Notes
                            .Where(d => !d.IsDelete)
                            .Select(d => new ArticleBase
                            {
                                Id = d.Id,
                                IsRedFlag = d.IsRedFlag,
                                TagDescription = "",
                                Title = d.Title,
                                Type = (int)ArticleType.Notes,
                                CreateTime = d.CreateTime,
                                Mood = d.Mood,
                                Weather = d.Weather
                            });
                    var notePageData = await noteQuery.ToListAsync();
                    result.Result = notePageData
                         .GroupBy(x => x.CreateTime.Year)
                         .Select(g => new ArticleGroupByYearResponse
                         {
                             Year = g.Key.ToString(),
                             ArticleList = g.OrderByDescending(x => x.CreateTime)
                                      .Select(ToArticleListResponse)
                                      .ToList(),
                             Count = g.Count()
                         })
                        .OrderByDescending(g => g.Year)
                        .ToList();
                    result.TotalNum = noteCount;
                    break;
            }

            return result;
        }

        /// <summary>
        /// 点赞闲书
        /// </summary>
        /// <param name="notesId"></param>
        /// <param name="fingerprint">指纹</param>
        /// <returns></returns>
        public async Task<bool> LikeNotes(string notesId, string fingerprint)
        {
            string cacheKey = $"notes:{notesId}:clients";
            //await RedisHelper.KeyDeleteAsync(cacheKey);
            var isLiked = await RedisHelper.SetContainsAsync(cacheKey, fingerprint);
            if (isLiked)
            {
                return false;
            }
            else
            {
                var notes = await _notes.WhereLoadEntityAsync(d => d.Id == Guid.Parse(notesId));
                notes.Like++;
                _notes.UpdateEntity(notes);
                await _notes.CommitAsync();

                await RedisHelper.SetAddAsync(cacheKey, fingerprint, TimeSpan.FromDays(30));
                return true;
            }
        }

        /// <summary>
        /// 点赞文章
        /// </summary>
        /// <param name="articleId"></param>
        /// <param name="fingerprint">指纹</param>
        /// <returns></returns>
        public async Task<bool> LikeArticle(string articleId, string fingerprint)
        {
            string cacheKey = $"article:{articleId}:clients";
            //await RedisHelper.KeyDeleteAsync(cacheKey);
            var isLiked = await RedisHelper.SetContainsAsync(cacheKey, fingerprint);
            if (isLiked)
            {
                return false;
            }
            else
            {
                var article = await _articleInfo.WhereLoadEntityAsync(d => d.Id == Guid.Parse(articleId));
                article.Like++;
                _articleInfo.UpdateEntity(article);
                await _notes.CommitAsync();

                await RedisHelper.SetAddAsync(cacheKey, fingerprint, TimeSpan.FromDays(30));
                return true;
            }
        }

        /// <summary>
        /// 数据映射
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        private ArticleListResponse ToArticleListResponse(ArticleBase item)
        {
            var type = (ArticleType)item.Type;
            return new ArticleListResponse
            {
                CreateTime = item.CreateTime,
                Date = item.CreateTime.ToString("dd/MM"),
                Id = item.Id.ToString(),
                IsRedFlag = item.IsRedFlag,
                TagDescription = type == ArticleType.Notes ? ($"{(item.Mood != null ? "心情：" + item.Mood + "/" : "")} {(item.Weather != null ? "天气：" + item.Weather + "/" : "")} {_notesName}") : item.TagDescription,
                Title = item.Title,
                Type = type,
                Years = item.CreateTime.ToString("yyyy"),
            };
        }


    }


}
